export class FARule  {
    constructor(
        public state:symbol,
        public character = "",
        public next_state:symbol,
    ){

    }
    applies_to(state:symbol,character:string){
        return this.state == state && this.character == character
    }

    follow(){
        return this.next_state;
    }

    toString(){
       
    }
}

class DFARulebook {
    constructor(
        public rules:FARule[] = []
    ){}

    next_state(state:symbol,character:string){
        return this.rule_for(state,character)?.follow()
    }

    rule_for(state:symbol,character:string):FARule | null{
        let nextRule:FARule|null = null;
        this.rules.forEach(rule => {
            if(rule.applies_to(state,character)){
                return nextRule = rule;
            }
        })
        return nextRule
    }
}

// let ruleBook = new DFARulebook([
//     new FARule(1,'a',2),
//     new FARule(1,'b',1),
//     new FARule(2,'a',2),
//     new FARule(2,'b',3),
//     new FARule(3,'a',3),
//     new FARule(3,'b',3)
// ])

class DFA {
    constructor(
        public current_state:symbol,
        public accept_states:symbol[],
        public rulebook:DFARulebook,
    ){
        
    }

    accepting(){
        return this.accept_states.indexOf(this.current_state) > -1 ;
    }

    read_character(character:string){
        this.current_state = this.rulebook.next_state(this.current_state,character) as symbol
    }
    
    read_string(input:string){
        let inputArray = input.split('');
        inputArray.forEach(i => {
            this.read_character(i)
        })
    }
}

class DFADesign{
    constructor(
        public start_state:symbol,
        public accept_states:symbol[],
        public rulebook:DFARulebook,
    ){
       
    }
    to_dfa(){
        return new DFA(this.start_state,this.accept_states,this.rulebook)
    }

    accepts(input:string){
        let dfa = this.to_dfa()
        dfa.read_string(input)
        return dfa.accepting()
    }
}
// console.log(ruleBook)
// console.log(ruleBook.next_state(1,'a'))
// console.log(ruleBook.next_state(1,'b'))
// console.log(ruleBook.next_state(2,'b'))

// console.log(new DFA(1,[1,3],ruleBook).accepting())
// console.log(new DFA(1,[3],ruleBook).accepting())


// let dfa = new DFA(1,[3],ruleBook);
// dfa.read_character('b');
// console.log(dfa.accepting())
// for(let i = 0; i< 3;i++){
//     dfa.read_character('a')
// }
// console.log(dfa.accepting())
// dfa.read_character('b');
// console.log(dfa.accepting())

// dfa.read_string('baaab')
// console.log(dfa.accepting())

// let dfa_design = new DFADesign(1,[3],ruleBook)

// console.log(dfa_design.accepts('a'))
// console.log(dfa_design.accepts('baa'))
// console.log(dfa_design.accepts('baba'))
